package com.easyclearance.controller;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.SortedMap;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.easyclearance.baseutil.SqlInjectInterceptor;
import com.easyclearance.baseutil.StringUtil;
import com.easyclearance.dao.OrderInfoMapper;
import com.easyclearance.dao.OrdertravpassportMapper;
import com.easyclearance.dao.PassportInfoMapper;
import com.easyclearance.dao.WxuserInfoMapper;
import com.easyclearance.entity.OrderInfo;
import com.easyclearance.entity.Ordertravpassport;
import com.easyclearance.entity.PassportInfo;
import com.easyclearance.entity.WxuserInfo;
import com.easyclearance.service.WxuserService;
import com.easyclearance.wxutils.HttpUtil;
import com.easyclearance.wxutils.PayCommonUtil;
import com.easyclearance.wxutils.PayConfigUtil;
import com.easyclearance.wxutils.WxloginUtil;
import com.easyclearance.wxutils.XMLUtil;

@CrossOrigin
@RestController
@RequestMapping(value = "/wxuserapi",method = RequestMethod.POST)
public class WxuserController extends BaseController {

	private final Logger logger = Logger.getLogger(WxuserController.class);
//	@Autowired
//	private ImgUtil imgUtil;
	@Autowired
	private WxloginUtil wxloginUtil;
//	@Autowired
//	private MailUtil mailUtil;
//	@Autowired
//	private FileControl fileControl;
	@Autowired
	private WxuserInfoMapper wxuserInfoMapper;
//	@Autowired
//	private MailInfoMapper mailInfoMapper;
	@Autowired
	private OrderInfoMapper orderInfoMapper;
//	@Autowired
//	private TravinfoCodeMapper travinfoCodeMapper;
	@Autowired
	private PassportInfoMapper passportInfoMapper;
//	@Autowired
//	private MalaysiaMadcRegUtil malaysiaMadcRegUtil;
//	@Autowired
//	private MalaysiatravinfoMapper malaysiatravinfoMapper;
//	@Autowired
//	private SingaporeTravInfoMapper singaporeTravInfoMapper;
	@Autowired
	private OrdertravpassportMapper ordertravpassportMapper;
//	@Autowired
//	private TravelitineraryMapper travelitineraryMapper;
//	@Autowired
//	private TravelCodeRelationMapper travelCodeRelationMapper;
	@Autowired
	private SqlInjectInterceptor sqlInjectInterceptor;
	@Autowired
	private WxuserService wxuserService;

    @RequestMapping("/decodingCode")
    @ResponseBody
    public Map<String, Object> decodeUserInfo(@RequestBody Map<String, Object> paramMap,
    		HttpServletRequest request, HttpServletResponse response) {
    	Map<String, Object> resultMap = new HashMap<String, Object>();

        try {
        	String code= "";
        	if (paramMap.containsKey("code") && StringUtils.isNotEmpty(paramMap.get("code").toString())) {
        		code = paramMap.get("code").toString();
			}else {
				throw new Exception("code为空");
			}
        	String iv = "";
        	if (paramMap.containsKey("iv") && StringUtils.isNotEmpty(paramMap.get("iv").toString())) {
        		iv = paramMap.get("iv").toString();
			}else {
				throw new Exception("iv为空");
			}
        	String encryptedData = "";
        	if (paramMap.containsKey("encryptedData") && StringUtils.isNotEmpty(paramMap.get("encryptedData").toString())) {
        		encryptedData = paramMap.get("encryptedData").toString();
			}else {
				throw new Exception("encryptedData为空");
			}

            /////////////////////////////////////////////////////////////////////
            //调用工具类中获取session_key的方法
            String sessionkey = wxloginUtil.get(code);
            //调用工具类中的解密方法，然后返回给小程序就OK了
            JSONObject userInfo = wxloginUtil.getUserInfo(encryptedData, sessionkey, iv);
            logger.error("用户信息："+JSON.toJSONString(userInfo));
            if (Objects.isNull(userInfo)) {
            	resultMap.put("success", true);
            	resultMap.put("message", "解密为null");
            	resultMap.put("data", new HashMap<>());
            } else {
            	//获取coin
            	String openId = userInfo.getString("openId");
            	//首先判断是否存在该用户信息
            	String city = userInfo.getString("city");
            	String gender = userInfo.getString("gender");
            	String nickName = userInfo.getString("nickName");
            	String avatarUrl = userInfo.getString("avatarUrl");
            	WxuserInfo wxuserInfo = wxuserInfoMapper.selectOne(new QueryWrapper<WxuserInfo>().eq("wxuser_id", openId));
            	if (Objects.nonNull(wxuserInfo)) {
                	wxuserInfo.setUserArea(city);
                	wxuserInfo.setWxuserId(openId);
                	wxuserInfo.setUserName(nickName);
                	wxuserInfo.setUserPictrue(avatarUrl);
                	wxuserInfo.setUserSex(gender);
                	wxuserInfoMapper.updateById(wxuserInfo);
				}else {
	            	WxuserInfo wxuserInfonew = new WxuserInfo();
	            	String id = StringUtil.getId();
	            	wxuserInfonew.setId(id);
	            	wxuserInfonew.setUserArea(city);
	            	wxuserInfonew.setWxuserId(openId);
	            	wxuserInfonew.setUserName(nickName);
	            	wxuserInfonew.setUserPictrue(avatarUrl);
	            	wxuserInfonew.setUserSex(gender);
	            	wxuserInfonew.setPubts(new Date());
	            	wxuserInfoMapper.insert(wxuserInfonew);
	            	wxuserInfo = wxuserInfonew;
				}
//            	String openId = userInfo.getString("openId");

            	resultMap = BaseController.correctReturn(wxuserInfo);
            }
        } catch (Exception e) {
            e.printStackTrace();
            resultMap = BaseController.exceptionReturn();
        }
        return resultMap;
    }
    
	@SuppressWarnings("unchecked")
	@ResponseBody
	@RequestMapping(value = "/mobOrder", produces = "Application/json; charset=utf-8")
	public Map<String, Object> mobOrder(@RequestBody Map<String, Object> paraMap,
			HttpServletRequest request, HttpServletResponse response) {

		Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			sqlInjectInterceptor.preHandle(request, response, paraMap);
			String orderId = paraMap.get("orderId").toString();
			// 判断是否
//			String uriString = request.getScheme() + "://" + request.getServerName();

			OrderInfo orderInfo = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>().eq("id", orderId));
//			logger.error("订单信息："+JSON.toJSONString(orderInfo));
			short ecPayStatus = orderInfo.getEcPayStatus();
			BigDecimal ecPayment = orderInfo.getEcPayment();
			//判断订单的支付状态
			if (Objects.equals(ecPayStatus, Short.parseShort("0")) && !Objects.equals(ecPayment, BigDecimal.ZERO)) {
				//支付金额
				int ecPaymentInt = ecPayment.multiply(BigDecimal.valueOf(100)).intValue();
				String userId = orderInfo.getUserId();
				String ecMerchantOrderNumber = orderInfo.getEcMerchantOrderNumber();
				//获取openid
				WxuserInfo wxuserInfo = wxuserInfoMapper.selectById(userId);
				if (Objects.nonNull(wxuserInfo)) {
					String openid = wxuserInfo.getWxuserId();
					// 账号信息
					String appid = PayConfigUtil.APP_ID; // appid
					// 出国宝旅行商户号信息
					String mch_id = PayConfigUtil.APP_MCH_ID; // 商业号
					String key = PayConfigUtil.API_KEY; // key

					String currTime = PayCommonUtil.getCurrTime();
					String strTime = currTime.substring(8);
					String strRandom = PayCommonUtil.buildRandom(4) + "";
					String nonce_str = strTime + strRandom;

					final String out_trade_no = ecMerchantOrderNumber+"_"+orderId.substring(orderId.length()-18);// 订单号
					String body = "团队易入境服务"; // 商品名称
					String spbill_create_ip = HttpUtil.localIp();// PayConfigUtil.CREATE_IP;
					// 回调接口
					String notify_url = PayConfigUtil.NOTIFY_ORDER_URL;
					String trade_type = "JSAPI";

					SortedMap<String, Object> packageParams = new TreeMap<String, Object>();
					// 设置请求参数(小程序ID)
					packageParams.put("appid", appid);
					// 设置请求参数(商户号)
					packageParams.put("mch_id", mch_id);
					// 设置请求参数(随机字符串)
					packageParams.put("nonce_str", nonce_str);
					// 设置请求参数(商品描述)
					packageParams.put("body", body);
					// 设置请求参数(商户订单号)
					packageParams.put("out_trade_no", out_trade_no);
					// 设置请求参数(总金额)
					packageParams.put("total_fee", String.valueOf(ecPaymentInt));
					// 设置请求参数(终端IP)
					packageParams.put("spbill_create_ip", spbill_create_ip);
					// 设置请求参数(通知地址)
					packageParams.put("notify_url", notify_url);
					// 设置请求参数(交易类型)
					packageParams.put("trade_type", trade_type);
					// 设置请求参数(openid)(在接口文档中 该参数 是否必填项 但是一定要注意 如果交易类型设置成'JSAPI'则必须传入openid)
					packageParams.put("openid", openid);
					// 调用逻辑传入参数按照字段名的 ASCII 码从小到大排序（字典序）
					String sign = PayCommonUtil.createSign("UTF-8", packageParams, key);
					packageParams.put("sign", sign);
					// 将参数 编写XML格式
					String requestXML = PayCommonUtil.getRequestXml(packageParams);
					logger.info(requestXML);
					
					
					String resXml = HttpUtil.postData(PayConfigUtil.UNIORDER_URL, requestXML);
					logger.info("ResultXML:\n" + resXml);

					String prepay_id = "";
//					String code_url = "";
					Map<String,Object> wxResultmap = XMLUtil.doXMLParse(resXml);
					String return_code = (String) wxResultmap.get("return_code");
					String result_code = (String) wxResultmap.get("result_code");
					if (return_code.equals("SUCCESS") && result_code.equals("SUCCESS")) {
						trade_type = (String) wxResultmap.get("trade_type");
						prepay_id = (String) wxResultmap.get("prepay_id");
//						code_url = (String) wxResultmap.get("code_url");
						logger.info("return_code:" + return_code);
						logger.info("prepay_id:" + prepay_id);
					}

					// 最后，设置定时器，超时后，自动取消订单
					// TODO,
					Timer timer = new Timer();
					timer.schedule(new TimerTask() {
						@Override
						public void run() {
							Ordertravpassport ordertravpassport = ordertravpassportMapper.selectOne(new QueryWrapper<Ordertravpassport>().eq("orderid", orderId));
							if (Objects.nonNull(ordertravpassport)) {
								OrderInfo orderInfos = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>().eq("id", out_trade_no));
								if (Objects.nonNull(orderInfos)) {
									short ecPayStatus2 = orderInfos.getEcPayStatus();
									if (Objects.equals(ecPayStatus2, Short.parseShort("0"))) {
										orderInfoMapper.delete(new QueryWrapper<OrderInfo>().eq("id", out_trade_no));
										ordertravpassportMapper.delete(new QueryWrapper<Ordertravpassport>().eq("orderid", out_trade_no).eq("ecppid", ordertravpassport.getEcppid()));
										passportInfoMapper.delete(new QueryWrapper<PassportInfo>().eq("id", ordertravpassport.getEcppid()));
										timer.cancel();
									}
								}
							}
						}
					}, 30 * 60 * 1000);
					// 时间戳
					strTime = currTime.substring(8);
					strRandom = PayCommonUtil.buildRandom(4) + "";
					String nonceStr = strTime + strRandom;
					// 签名加密方式
					String signType = "MD5";
					// 数据加
					SortedMap<String, Object> packageParams2 = new TreeMap<String, Object>();
					String ts = "" + ((new Date()).getTime()) / 1000L;
					packageParams2.put("appId", PayConfigUtil.APP_ID);
					packageParams2.put("timeStamp", ts);
					packageParams2.put("nonceStr", nonceStr);
					packageParams2.put("package", "prepay_id=" + prepay_id);
					packageParams2.put("signType", signType);

					String paySign = PayCommonUtil.createSign("UTF-8", packageParams2, key);
					packageParams2.put("sign", paySign);
					logger.info("paySign:" + paySign);
					resultMap = BaseController.correctReturn(packageParams2);
				}else {
					resultMap = BaseController.otherResultReturn(1, "未获取到订单对应的用户信息");
				}
			}else {
				resultMap = BaseController.otherResultReturn(1, "当前订单非待支付状态或者支付金额为0");
			}
		} catch (Exception e) {
			e.printStackTrace();
			resultMap = BaseController.otherResultReturn(1,e.getMessage());
		}
		return resultMap;
	}

	@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
	@RequestMapping("/notifyOrder")
	@ResponseBody
	public void notifyOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
		logger.info("into notifyOrder");
		// 读取参数
		InputStream inputStream;
		StringBuffer sb = new StringBuffer();
		inputStream = request.getInputStream();
		String s;
		BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
		while ((s = in.readLine()) != null) {
			sb.append(s);
		}
		in.close();
		inputStream.close();

		// 解析xml成map
		Map<String, String> map = new HashMap<String, String>();
		logger.info("Weixin Notify received:\n" + sb.toString());
		map = XMLUtil.doXMLParse(sb.toString());

		// 过滤空 设置 TreeMap
		SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
		Iterator it = map.keySet().iterator();
		while (it.hasNext()) {
			String parameter = (String) it.next();
			String parameterValue = map.get(parameter);

			String v = "";
			if (null != parameterValue) {
				v = parameterValue.trim();
			}
			packageParams.put(parameter, v);
		}

		// 出国宝旅行商户号key信息
		String key = PayConfigUtil.API_KEY; // key
		logger.error("返回结果："+JSON.toJSONString(packageParams));
		// 判断签名是否正确
		if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {
			// ------------------------------
			// 处理业务开始
			// ------------------------------
			String resXml = "";
			if ("SUCCESS".equals(packageParams.get("result_code"))) {
				// 这里是支付成功
				// ////////执行自己的业务逻辑////////////////
				String mch_id = (String) packageParams.get("mch_id");
				String out_trade_no = (String) packageParams.get("out_trade_no");
				String total_fee = (String) packageParams.get("total_fee");
				String transaction_id = (String) packageParams.get("transaction_id");
				logger.info("mch_id:" + mch_id);
				logger.info("out_trade_no:" + out_trade_no);// 订单号
				logger.info("total_fee:" + total_fee);
				String[] paramArr = out_trade_no.split("_");
				String ecMerchantOrderNumber = paramArr[0];
				String orderidleftlike = paramArr[1];
				////////// 执行自己的业务逻辑////////////////
				OrderInfo orderInfo = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>().eq("ec_merchant_order_number", ecMerchantOrderNumber).likeLeft("id", orderidleftlike));
				logger.info("-------------" + orderInfo + "----------------");
				short ecPayStatus = orderInfo.getEcPayStatus();
				BigDecimal ecPayment = orderInfo.getEcPayment();
				String orderid = orderInfo.getId();
				if (Objects.equals(ecPayStatus, Short.parseShort("0"))) {
					OrderInfo orderInfo2 = new OrderInfo();
					String payTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS EEE").format(new Date());
					try {
						orderInfo2.setEcPayTime(payTime);
						orderInfo2.setId(orderInfo.getId());
						orderInfo2.setEcStatus(Short.parseShort("1"));
						orderInfo2.setEcPayStatus(Short.parseShort("1"));
						orderInfo2.setEcPayTransactionId(transaction_id);
						orderInfo2.setEcPayMethod("微信支付");
						// 修改支付状态
						orderInfoMapper.updateById(orderInfo2);
					} catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
					}
					try {
						wxuserService.afterPaySubmit(orderid);
					} catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
					}
					// 打印支付成功
					logger.info("--------Pay Success!---------");
					// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
					resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
							+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
				} else {// 订单已失效，支付失败！
					logger.info("Pay Fail, error info：" + packageParams.get("err_code") + "  order id:"
							+ (null == orderInfo ? "" : orderInfo.getId()));
					resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
							+ "<return_msg><![CDATA[Report empty]]></return_msg>" + "</xml> ";
				}
//				}
			} else {
				logger.info("Pay Fail, error code： " + packageParams.get("err_code"));
				resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
						+ "<return_msg><![CDATA[Report empty]]></return_msg>" + "</xml> ";
			}
			logger.info("notifyVenueOrder resXml： " + resXml);
			// ------------------------------
			// 处理业务完毕
			// ------------------------------
			BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
			out.write(resXml.getBytes());
			out.flush();
			out.close();
		} else {
			logger.info("signature checking fail");
		}
	}

	
	@RequestMapping(value = "/submit")
	public Map<String, Object> submitMap (@RequestBody Map<String, Object> paramMap,HttpServletRequest request,HttpServletResponse  response){
		Map<String, Object> resultMap = new HashMap<>();
		try {
			String id = paramMap.get("id").toString();
			wxuserService.afterPaySubmit(id);
			resultMap = BaseController.correctReturn(new JSONObject());
		} catch (Exception e) {
			// TODO: handle exception
			resultMap = BaseController.exceptionReturn();
		}
		return resultMap;
	}
}
